from sqlalchemy.orm import Session
from sqlalchemy import or_, and_, desc
from app.models.chat import Chat, ChatParticipant, Message, ChatType
from app.models.user import User
from app.schemas.chat import MessageCreate, PrivateChatCreate, GroupChatCreate
from typing import List, Optional, Tuple, Dict
import datetime

def get_chat(db: Session, chat_id: int) -> Optional[Chat]:
    """获取聊天会话"""
    return db.query(Chat).filter(Chat.id == chat_id).first()

def get_chat_participants(db: Session, chat_id: int) -> List[ChatParticipant]:
    """获取聊天参与者列表"""
    return db.query(ChatParticipant).filter(ChatParticipant.chat_id == chat_id).all()

def get_chat_participant(db: Session, chat_id: int, user_id: int) -> Optional[ChatParticipant]:
    """获取特定用户的聊天参与者记录"""
    return db.query(ChatParticipant).filter(
        ChatParticipant.chat_id == chat_id,
        ChatParticipant.user_id == user_id
    ).first()

def get_private_chat(db: Session, user_id1: int, user_id2: int) -> Optional[Chat]:
    """查找两个用户之间的私聊会话"""
    # 查找包含这两个用户的私聊会话
    chats = db.query(Chat).filter(Chat.chat_type == ChatType.PRIVATE).all()
    
    for chat in chats:
        participants = get_chat_participants(db, chat.id)
        participant_ids = [p.user_id for p in participants]
        if user_id1 in participant_ids and user_id2 in participant_ids and len(participant_ids) == 2:
            return chat
    
    return None

def create_private_chat(db: Session, user_id: int, chat_create: PrivateChatCreate) -> Tuple[Chat, bool]:
    """创建私聊会话，返回会话和是否新创建的标志"""
    # 检查是否已存在私聊
    existing_chat = get_private_chat(db, user_id, chat_create.recipient_id)
    if existing_chat:
        return existing_chat, False
    
    # 创建新私聊
    db_chat = Chat(
        chat_type=ChatType.PRIVATE,
        name=None,
        campsite_id=None
    )
    db.add(db_chat)
    db.commit()
    db.refresh(db_chat)
    
    # 添加参与者
    participants = [
        ChatParticipant(chat_id=db_chat.id, user_id=user_id, is_admin=True),
        ChatParticipant(chat_id=db_chat.id, user_id=chat_create.recipient_id, is_admin=False)
    ]
    
    for participant in participants:
        db.add(participant)
    
    db.commit()
    return db_chat, True

def create_group_chat(db: Session, user_id: int, chat_create: GroupChatCreate) -> Chat:
    """创建群聊会话"""
    # 创建群聊
    db_chat = Chat(
        chat_type=ChatType.GROUP,
        name=chat_create.name,
        campsite_id=chat_create.campsite_id
    )
    db.add(db_chat)
    db.commit()
    db.refresh(db_chat)
    
    # 添加创建者（管理员）
    db_creator = ChatParticipant(
        chat_id=db_chat.id,
        user_id=user_id,
        is_admin=True
    )
    db.add(db_creator)
    
    # 添加其他参与者
    for participant_id in chat_create.participant_ids:
        if participant_id != user_id:  # 避免重复添加创建者
            db_participant = ChatParticipant(
                chat_id=db_chat.id,
                user_id=participant_id,
                is_admin=False
            )
            db.add(db_participant)
    
    db.commit()
    return db_chat

def get_user_chats(db: Session, user_id: int, skip: int = 0, limit: int = 100) -> List[Dict]:
    """获取用户的聊天会话列表，包含未读消息数和最新消息"""
    # 获取用户参与的所有聊天
    participant_records = db.query(ChatParticipant).filter(
        ChatParticipant.user_id == user_id
    ).all()
    
    chat_ids = [p.chat_id for p in participant_records]
    
    if not chat_ids:
        return []
    
    # 获取这些聊天的详细信息
    chats = db.query(Chat).filter(Chat.id.in_(chat_ids)).order_by(Chat.updated_at.desc()).offset(skip).limit(limit).all()
    
    # 获取每个聊天的最新消息和未读消息数
    result = []
    for chat in chats:
        # 获取最新消息
        latest_message = db.query(Message).filter(
            Message.chat_id == chat.id
        ).order_by(Message.created_at.desc()).first()
        
        # 获取用户在此聊天中的参与记录
        participant = get_chat_participant(db, chat.id, user_id)
        
        # 计算未读消息数
        unread_count = 0
        if participant and participant.last_read_message_id:
            unread_count = db.query(Message).filter(
                Message.chat_id == chat.id,
                Message.id > participant.last_read_message_id
            ).count()
        elif latest_message:  # 如果用户从未读过任何消息
            unread_count = db.query(Message).filter(
                Message.chat_id == chat.id
            ).count()
        
        # 组装数据
        chat_data = {
            "id": chat.id,
            "chat_type": chat.chat_type,
            "name": chat.name,
            "campsite_id": chat.campsite_id,
            "created_at": chat.created_at,
            "updated_at": chat.updated_at,
            "last_message": latest_message,
            "unread_count": unread_count
        }
        
        # 如果是私聊，获取对方的信息作为名称
        if chat.chat_type == ChatType.PRIVATE:
            participants = get_chat_participants(db, chat.id)
            for p in participants:
                if p.user_id != user_id:
                    other_user = db.query(User).filter(User.id == p.user_id).first()
                    if other_user:
                        chat_data["name"] = other_user.username
                        break
        
        result.append(chat_data)
    
    return result

def get_messages(db: Session, chat_id: int, skip: int = 0, limit: int = 50) -> List[Message]:
    """获取聊天消息列表"""
    return db.query(Message).filter(
        Message.chat_id == chat_id
    ).order_by(Message.created_at.desc()).offset(skip).limit(limit).all()

def create_message(db: Session, chat_id: int, user_id: int, message: MessageCreate) -> Optional[Message]:
    """创建新消息"""
    # 检查聊天会话是否存在
    chat = get_chat(db, chat_id)
    if not chat:
        return None
    
    # 检查用户是否是聊天参与者
    participant = get_chat_participant(db, chat_id, user_id)
    if not participant and chat.chat_type != ChatType.SYSTEM:  # 系统消息可能没有发送者
        return None
    
    # 创建消息
    db_message = Message(
        chat_id=chat_id,
        sender_id=user_id if chat.chat_type != ChatType.SYSTEM else None,
        content=message.content,
        content_type=message.content_type,
        media_url=message.media_url,
        is_read=False
    )
    db.add(db_message)
    
    # 更新聊天会话的更新时间
    chat.updated_at = datetime.datetime.utcnow()
    
    db.commit()
    db.refresh(db_message)
    return db_message

def mark_messages_as_read(db: Session, chat_id: int, user_id: int, message_id: Optional[int] = None) -> bool:
    """将消息标记为已读"""
    # 检查用户是否是聊天参与者
    participant = get_chat_participant(db, chat_id, user_id)
    if not participant:
        return False
    
    # 如果提供了特定消息ID，则更新到该消息
    if message_id:
        participant.last_read_message_id = message_id
    else:
        # 否则更新到最新消息
        latest_message = db.query(Message).filter(
            Message.chat_id == chat_id
        ).order_by(Message.created_at.desc()).first()
        
        if latest_message:
            participant.last_read_message_id = latest_message.id
    
    db.commit()
    return True

def add_participant_to_chat(db: Session, chat_id: int, user_id: int, is_admin: bool = False) -> Optional[ChatParticipant]:
    """将用户添加到聊天会话"""
    # 检查聊天会话是否存在
    chat = get_chat(db, chat_id)
    if not chat or chat.chat_type != ChatType.GROUP:  # 只能添加用户到群聊
        return None
    
    # 检查用户是否已经是参与者
    existing_participant = get_chat_participant(db, chat_id, user_id)
    if existing_participant:
        return existing_participant
    
    # 添加参与者
    db_participant = ChatParticipant(
        chat_id=chat_id,
        user_id=user_id,
        is_admin=is_admin
    )
    db.add(db_participant)
    db.commit()
    db.refresh(db_participant)
    return db_participant

def remove_participant_from_chat(db: Session, chat_id: int, user_id: int) -> bool:
    """从聊天会话中移除用户"""
    # 检查聊天会话是否存在
    chat = get_chat(db, chat_id)
    if not chat or chat.chat_type != ChatType.GROUP:  # 只能从群聊中移除用户
        return False
    
    # 检查用户是否是参与者
    participant = get_chat_participant(db, chat_id, user_id)
    if not participant:
        return False
    
    # 移除参与者
    db.delete(participant)
    db.commit()
    return True

def create_system_notification(db: Session, content: str, user_ids: List[int] = None) -> List[Message]:
    """创建系统通知，可以发送给特定用户或所有用户"""
    # 创建或获取系统消息聊天
    system_chat = db.query(Chat).filter(Chat.chat_type == ChatType.SYSTEM).first()
    if not system_chat:
        system_chat = Chat(
            chat_type=ChatType.SYSTEM,
            name="系统通知"
        )
        db.add(system_chat)
        db.commit()
        db.refresh(system_chat)
    
    messages = []
    
    # 如果没有指定用户，则发送给所有用户
    if not user_ids:
        all_users = db.query(User).filter(User.is_active == True).all()
        user_ids = [user.id for user in all_users]
    
    # 为每个用户创建消息
    for user_id in user_ids:
        # 检查用户是否已经是系统通知的参与者
        participant = get_chat_participant(db, system_chat.id, user_id)
        if not participant:
            # 添加用户为系统通知的参与者
            participant = ChatParticipant(
                chat_id=system_chat.id,
                user_id=user_id,
                is_admin=False
            )
            db.add(participant)
        
        # 创建系统消息
        message = Message(
            chat_id=system_chat.id,
            sender_id=None,  # 系统消息没有发送者
            content=content,
            content_type="text",
            is_read=False
        )
        db.add(message)
        messages.append(message)
    
    db.commit()
    
    # 刷新所有消息对象
    for message in messages:
        db.refresh(message)
    
    return messages 